<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 沙箱 防止应用加载的时候 对widow造成污染 -->

    <!-- a-> 更改了window属性 删掉 -->
    <!-- b-> 更改了window属性 -->

    <!-- 先保留a应用的属性  失活的时候 把修改的属性存起来，激活的时候还原回来 -->
    <!-- 快照 浪费内存，因为要给window拍照 -->

    <script>
        /*
        class SnapshotSandbox {
            constructor(){
                this.modifyPropsMap = {}; // 存储全局哪些属性被修改了
            }
            active(){
                this.windowSnapShot = {};
                // 给window拍照
                Object.keys(window).forEach(prop=>{
                    this.windowSnapShot[prop] = window[prop]
                })
                Object.keys(this.modifyPropsMap).forEach(prop=>{
                    window[prop] = this.modifyPropsMap[prop]
                })
            }
            inactive(){
                this.modifyPropsMap = {}
                Object.keys(window).forEach(prop=>{
                    if(window[prop] !== this.windowSnapShot[prop]){
                        this.modifyPropsMap[prop] = window[prop];  
                        window[prop] = this.windowSnapShot[prop];
                    }
                })
            }
        }
        let sandbox = new SnapshotSandbox();
        sandbox.active();
        window.a = 100;
        window.b = 200;
        sandbox.inactive();
        console.log(window.a,window.b)
        sandbox.active();
        console.log(window.a,window.b)

        // 缺点就是 浪费内存， **快照**， 存储修改的或者添加的属性，不要给window拍照
        */
        // proxy兼容性问题

        /*
        class LegacySandbox {
            constructor(){
                // 1) 修改的内容  2) 新增的内容  3) 不管修改还是新增的
                this.modifyPropsMap = new Map();
                this.addedPropsMap = new Map();
                this.currentPropsMap = new Map();

                const fakeWindow = Object.create(null)
                const proxy = new Proxy(fakeWindow,{
                    get:(target,key,recevier)=>{
                        return window[key]
                    },
                    set:(target,key,value)=>{
                        if(!window.hasOwnProperty(key)){
                            // 添加的属性
                            this.addedPropsMap.set(key,value)
                        }else if(!this.modifyPropsMap.has(key)){
                            // 保存修改的前的值
                            this.modifyPropsMap.set(key,window[key])
                        }
                        // 所有的修改操作都保留了一份最新的
                        this.currentPropsMap.set(key,value);
                        window[key] = value;// 修改成最新的内容 
                    },
                })
                this.proxy = proxy
            }
            setWindowProp(key,value){
                if(value == undefined){
                    delete window[key];
                }else{
                    window[key] = value; // 覆盖修改前的
                }
            }
            active(){
                this.currentPropsMap.forEach((value,key)=>{
                    this.setWindowProp(key,value)
                })
            }
            inactive(){
                this.modifyPropsMap.forEach((value,key)=>{
                    this.setWindowProp(key,value)
                })
                this.addedPropsMap.forEach((value,key)=>{
                    this.setWindowProp(key,undefined)
                })
            }
        }
        let sandbox = new LegacySandbox();
        sandbox.proxy.a = 100;
        console.log(window.a,sandbox.proxy.a)
        sandbox.inactive();
        console.log(window.a,sandbox.proxy.a)
        sandbox.active();
        console.log(window.a,sandbox.proxy.a)
        // 基于proxy的沙箱 （如果两个应用一起运行 window就一个 就乱了。。。）
        // 节约内存 
        // 快照 、 基于proxy 只能单例的情况下使用，同时加载两个应用就会混乱 风险

        (function(window){
            window.a = 100;
        })(sandbox.proxy)
        */

        // 多个实例来实现
        class ProxySandbox {
            constructor(){
                this.running = false
                const fakeWindow = Object.create(null)
                this.proxy = new Proxy(fakeWindow,{
                    get:(target,key)=>{
                        return key in target ? target[key]:window[key]
                    },
                    set:(target,key,value)=>{
                        if(this.running) {
                            target[key] = value;
                        }
                        return true;
                    }
                    // 修改不在操作window属性
                })
            }
            active(){
                if(!this.running) this.running = true
            }
            inactive(){
                this.running = false;
            }
        }
        let sandbox1 = new ProxySandbox();
        let sandbox2 = new ProxySandbox();
        sandbox1.active();
        sandbox2.active();
        sandbox1.proxy.a = 100;
        sandbox2.proxy.a = 100; // 不会影响window
        console.log(sandbox1.proxy.a)
        console.log(sandbox2.proxy.a)
        sandbox1.inactive();
        sandbox2.inactive();
        sandbox1.proxy.a = 200;
        sandbox2.proxy.a = 200;
        console.log(sandbox1.proxy.a,window.a)
        console.log(sandbox2.proxy.a)

        (function(window){

        })(sandbox1.proxy)


        (function(window){

        })(sandbox2.proxy)
    </script>

</body>
</html>